package net.xxcxcxcx.xc_enhancedmob.render.boss_bar.unit;

import net.minecraft.entity.mob.MobEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;
import net.xxcxcxcx.xc_enhancedmob.packet.dirty.DataTracking;
import net.xxcxcxcx.xc_enhancedmob.render.boss_bar.unit.type.BossBarTypeHelper;
import net.xxcxcxcx.xc_enhancedmob.render.boss_bar.unit.type.cover.BossBarCoverType;
import net.xxcxcxcx.xc_enhancedmob.render.boss_bar.unit.type.reality.BossBarRealityType;

import java.util.UUID;

/**
 * CustomBossBar的基础
 * <p>是具体一个CustomBossbar的实现
 * <p>其本质上是一个分层血条
 * <p>|=======-----|
 */
public abstract class BaseCustomBossBar implements CustomBossBar {
    private final DataTracking<UUID> uuid = new DataTracking<>();//唯一uuid识别码
    private final DataTracking<Text> name = new DataTracking<>();//CustomBossBar的名称
    private final DataTracking<Integer> SortCount = new DataTracking<>();//sort排序
    private final DataTracking<Float> MaxCount = new DataTracking<>();//血量最大值
    private final DataTracking<Float> NowCount = new DataTracking<>();//当前血量值
    private final DataTracking<Integer> LayerCount = new DataTracking<>();//血量会分多少层显示
    private final DataTracking<BossBarRealityType> RealityType = new DataTracking<>();//贴图的类型
    private final DataTracking<Boolean> darkenSky = new DataTracking<>(false);//是否会使背景变暗（未实装）
    private final DataTracking<Boolean> dragonMusic = new DataTracking<>(false);//是否会播放末影龙音乐（未实装）
    private final DataTracking<Boolean> thickenFog = new DataTracking<>(false);//是否会产生迷雾（未实装）
    private final DataTracking<Boolean> needMeterCover = new DataTracking<>();//是否渲染计量条
    private final DataTracking<BossBarCoverType> MeterCoverType = new DataTracking<>();//渲染的血条的计量条纹理

    private boolean dirty;

    public BaseCustomBossBar() {

    }

    public BaseCustomBossBar(UUID uuid, Text name, BossBarRealityType RealityType, float MaxCount, float NowCount, int Layer) {
        this(uuid, name, RealityType, MaxCount, NowCount, Layer, false, null);
    }

    public BaseCustomBossBar(UUID uuid, Text name, BossBarRealityType RealityType, float MaxCount, float NowCount, int Layer, boolean needMeterCover, BossBarCoverType MeterCoverType) {
        this(uuid, name, RealityType, MaxCount, NowCount, Layer, needMeterCover, MeterCoverType, 0);
    }

    public BaseCustomBossBar(UUID uuid, Text name, BossBarRealityType RealityType, float MaxCount, float NowCount, int Layer, boolean needMeterCover, BossBarCoverType MeterCoverType, int sortCount) {
        this.setUuid(uuid);
        this.setName(name);
        this.setRealityType(RealityType);
        this.setMaxCount(MaxCount);
        this.setNowCount(NowCount);
        this.setLayerCount(Layer);
        this.setNeedMeterCover(needMeterCover);
        this.setMeterCoverType(MeterCoverType);
        this.setSortCount(sortCount);
        getUuid().setDirty(false);
        getName().setDirty(false);
        getRealityType().setDirty(false);
        getMaxCount().setDirty(false);
        getNowCount().setDirty(false);
        getLayerCount().setDirty(false);
        getNeedMeterCover().setDirty(false);
        getMeterCoverType().setDirty(false);
        getSortCount().setDirty(false);
    }


    @Override
    public void writeDirtyCustomDataToNbt(NbtCompound nbt) {
        if (getUuid().isDirty()) {
            getUuid().setDirty(false);
            nbt.putUuid("Uuid", getUuid().getValue());
        }
        if (getName().isDirty()) {
            getName().setDirty(false);
            nbt.putString("Name", Text.Serializer.toJson(getName().getValue()));
        }
        if (getMaxCount().isDirty()) {
            getMaxCount().setDirty(false);
            nbt.putFloat("MaxCount", getMaxCount().getValue());
        }
        if (getNowCount().isDirty()) {
            getNowCount().setDirty(false);
            nbt.putFloat("NowCount", getNowCount().getValue());
        }
        if (getLayerCount().isDirty()) {
            getLayerCount().setDirty(false);
            nbt.putInt("LayerCount", getLayerCount().getValue());
        }
        if (getRealityType().isDirty()) {
            getRealityType().setDirty(false);
            NbtCompound type = new NbtCompound();
            getRealityType().getValue().writeCustomDataToNbt(type);
            nbt.put("type", type);
        }
        if (getDarkenSky().isDirty()) {
            getDarkenSky().setDirty(false);
            nbt.putBoolean("darkenSky", getDarkenSky().getValue());
        }
        if (getDragonMusic().isDirty()) {
            getDragonMusic().setDirty(false);
            nbt.putBoolean("dragonMusic", getDragonMusic().getValue());
        }
        if (getThickenFog().isDirty()) {
            getThickenFog().setDirty(false);
            nbt.putBoolean("thickenFog", getThickenFog().getValue());
        }
        if (getNeedMeterCover().isDirty()) {
            getNeedMeterCover().setDirty(false);
            nbt.putBoolean("needMeterCover", getNeedMeterCover().getValue());
        }
        if (getMeterCoverType().isDirty()) {
            getMeterCoverType().setDirty(false);
            NbtCompound Cover = new NbtCompound();
            getMeterCoverType().getValue().writeCustomDataToNbt(Cover);
            nbt.put("Cover", Cover);
        }
        if (getSortCount().isDirty()) {
            getSortCount().setDirty(false);
            nbt.putInt("SortCount", getSortCount().getValue());
        }
    }

    @Override
    public void readDirtyCustomDataFromNbt(NbtCompound nbt) {
        if (nbt.contains("Uuid")) setUuid(nbt.getUuid("Uuid"));
        if (nbt.contains("Name")) setName(Text.Serializer.fromJson(nbt.getString("Name")));
        if (nbt.contains("SortCount")) setSortCount(nbt.getInt("SortCount"));
        if (nbt.contains("MaxCount")) setMaxCount(nbt.getFloat("MaxCount"));
        if (nbt.contains("NowCount")) setNowCount(nbt.getFloat("NowCount"));
        if (nbt.contains("LayerCount")) setLayerCount(nbt.getInt("LayerCount"));
        if (nbt.contains("type")) setRealityType(BossBarTypeHelper.makeBossBarFromNbt(nbt.getCompound("type")));
        if (nbt.contains("darkenSky")) setDarkenSky(nbt.getBoolean("darkenSky"));
        if (nbt.contains("dragonMusic")) setDragonMusic(nbt.getBoolean("dragonMusic"));
        if (nbt.contains("thickenFog")) setThickenFog(nbt.getBoolean("thickenFog"));
        if (nbt.contains("needMeterCover")) setNeedMeterCover(nbt.getBoolean("needMeterCover"));
        if (nbt.contains("Cover"))
            setMeterCoverType(BossBarTypeHelper.makeBossBarCoverFromNbt(nbt.getCompound("Cover")));
    }

    @Override
    public void writeCustomDataToNbt(NbtCompound nbt) {
        nbt.putUuid("Uuid", getUuid().getValue());
        nbt.putString("Name", Text.Serializer.toJson(getName().getValue()));
        nbt.putInt("SortCount", getSortCount().getValue());
        nbt.putFloat("MaxCount", getMaxCount().getValue());
        nbt.putFloat("NowCount", getNowCount().getValue());
        nbt.putInt("LayerCount", getLayerCount().getValue());
        NbtCompound type = new NbtCompound();
        getRealityType().getValue().writeCustomDataToNbt(type);
        nbt.put("Reality", type);
        nbt.putBoolean("darkenSky", getDarkenSky().getValue());
        nbt.putBoolean("dragonMusic", getDragonMusic().getValue());
        nbt.putBoolean("thickenFog", getThickenFog().getValue());
        nbt.putBoolean("needMeterCover", getNeedMeterCover().getValue());
        if (getNeedMeterCover().getValue()) {
            NbtCompound Cover = new NbtCompound();
            getMeterCoverType().getValue().writeCustomDataToNbt(Cover);
            nbt.put("Cover", Cover);
        }
    }

    @Override
    public void readCustomDataFromNbt(NbtCompound nbt) {
        setUuid(nbt.getUuid("Uuid"));
        setName(Text.Serializer.fromJson(nbt.getString("Name")));
        setSortCount(nbt.getInt("SortCount"));
        setMaxCount(nbt.getFloat("MaxCount"));
        setNowCount(nbt.getFloat("NowCount"));
        setLayerCount(nbt.getInt("LayerCount"));
        setRealityType(BossBarTypeHelper.makeBossBarFromNbt(nbt.getCompound("Reality")));
        setDarkenSky(nbt.getBoolean("darkenSky"));
        setDragonMusic(nbt.getBoolean("dragonMusic"));
        setThickenFog(nbt.getBoolean("thickenFog"));
        setNeedMeterCover(nbt.getBoolean("needMeterCover"));
        if (getNeedMeterCover().getValue()) {
            setMeterCoverType(BossBarTypeHelper.makeBossBarCoverFromNbt(nbt.getCompound("Cover")));
        }
    }

    @Override
    public DataTracking<UUID> getUuid() {
        return uuid;
    }

    @Override
    public void setUuid(UUID uuid) {
        this.uuid.setValue(uuid);
        if (this.uuid.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Text> getName() {
        return name;
    }

    @Override
    public void setName(Text name) {
        this.name.setValue(name);
        if (this.name.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Float> getMaxCount() {
        return MaxCount;
    }

    @Override
    public void setMaxCount(float maxCount) {
        MaxCount.setValue(maxCount);
        if (this.MaxCount.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Float> getNowCount() {
        return NowCount;
    }

    @Override
    public void setNowCount(float nowCount) {
        NowCount.setValue(nowCount);
        if (this.NowCount.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Integer> getLayerCount() {
        return LayerCount;
    }

    @Override
    public void setLayerCount(int layerCount) {
        LayerCount.setValue(layerCount);
        if (this.LayerCount.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<BossBarRealityType> getRealityType() {
        return RealityType;
    }

    @Override
    public void setRealityType(BossBarRealityType type) {
        this.RealityType.setValue(type);
        if (this.RealityType.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Boolean> getDarkenSky() {
        return darkenSky;
    }

    @Override
    public void setDarkenSky(boolean darkenSky) {
        this.darkenSky.setValue(darkenSky);
        if (this.darkenSky.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Boolean> getDragonMusic() {
        return dragonMusic;
    }

    @Override
    public void setDragonMusic(boolean dragonMusic) {
        this.dragonMusic.setValue(dragonMusic);
        if (this.dragonMusic.isDirty()) setDirty(true);
    }

    @Override
    public DataTracking<Boolean> getThickenFog() {
        return thickenFog;
    }

    @Override
    public void setThickenFog(boolean thickenFog) {
        this.thickenFog.setValue(thickenFog);
        if (this.thickenFog.isDirty()) setDirty(true);
    }

    @Override
    public boolean getDirty() {
        return dirty;
    }

    @Override
    public void setDirty(Boolean dirty) {
        this.dirty = dirty;
    }

    public DataTracking<Boolean> getNeedMeterCover() {
        return needMeterCover;
    }

    public void setNeedMeterCover(boolean needMeterCover) {
        this.needMeterCover.setValue(needMeterCover);
        if (this.needMeterCover.isDirty()) setDirty(true);
    }

    public DataTracking<BossBarCoverType> getMeterCoverType() {
        return MeterCoverType;
    }

    public void setMeterCoverType(BossBarCoverType meterCoverType) {
        MeterCoverType.setValue(meterCoverType);
        if (this.MeterCoverType.isDirty()) setDirty(true);
    }

    @Override
    public void tick(MobEntity mobEntity) {

    }

    @Override
    public DataTracking<Integer> getSortCount() {
        return SortCount;
    }

    @Override
    public void setSortCount(int sortCount) {
        this.SortCount.setValue(sortCount);
        if (this.SortCount.isDirty()) setDirty(true);
    }
}
